home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / MACtive Desktop / Source / Sources / Notice.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-14  |  7.1 KB  |  340 lines  |  [TEXT/CWIE]

  1. #include <ctype.h>
  2. #include <Icons.h>
  3. #include <Fonts.h>
  4. #include <Notification.h>
  5. #include <Resources.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "Main.h"
  9. #include "Notice.h"
  10. #include "QDContext.h"
  11. #include "StringUtils.h"
  12.  
  13.  
  14.  
  15.  
  16.  
  17. extern Boolean                        gHasAppearance;
  18.  
  19.  
  20.  
  21.  
  22.  
  23. void PreflightNotice(Boolean blockEvents)
  24. {
  25.     char        name[32];
  26.     EventRecord    event;
  27.     Str255        msg;
  28.     NMRec        nmpb;
  29.     OSStatus    err;
  30.     
  31.     
  32.     // Are we the front process?
  33.     if (WeAreFrontProcess())
  34.         return;
  35.     
  36.     // Post a notification, and wait until
  37.     // our process is switched to the front.
  38.     GetAppNameCString(name);
  39.     msg[0] = sprintf((char*)&msg[1],"%s requires your attention.  Please bring %s to the front.",name,name);
  40.     
  41.     memset(&nmpb,0,sizeof(nmpb));
  42.     nmpb.qType = nmType;
  43.     nmpb.nmMark = 1;
  44.     
  45.     err = GetIconSuite(&nmpb.nmIcon,128,svAllSmallData);
  46.     if (err != noErr)
  47.         nmpb.nmIcon = NULL;
  48.     
  49.     nmpb.nmSound = (Handle)-1;
  50.     nmpb.nmStr = msg;
  51.     NMInstall(&nmpb);
  52.     
  53.     while(!WeAreFrontProcess())
  54.         SubEventLoop(blockEvents ? 0 : everyEvent);
  55.     
  56.     NMRemove(&nmpb);
  57.     if (nmpb.nmIcon) DisposeIconSuite(nmpb.nmIcon,true);
  58.     if (nmpb.nmResp) DisposeRoutineDescriptor(nmpb.nmResp);
  59. }
  60.  
  61.  
  62.  
  63.  
  64.  
  65. void PostNotice(AlertType type,const StringPtr error,const StringPtr detail)
  66. {
  67.     AlertStdAlertParamRec        param;
  68.     short                        item;
  69.     
  70.     
  71.     // Ensure we are front process.
  72.     PreflightNotice(false);
  73.     
  74.     // Do it our way..call CompatibleStandardAlert and we'll be done.
  75.     param.movable = false;
  76.     param.helpButton = false;
  77.     param.filterProc = NULL;
  78.     param.defaultText = (StringPtr)-1L;                // default = "OK"
  79.     param.cancelText = NULL;                        // no cancel button
  80.     param.otherText = NULL;                            // no other button
  81.     param.defaultButton = kAlertStdAlertOKButton;
  82.     param.cancelButton = 0;
  83.     param.position = 0;                                // Alert position on main screen
  84.         
  85.     CompatibleStandardAlert(type,error,detail,¶m,&item);
  86. }
  87.  
  88.  
  89.  
  90.  
  91.  
  92. Boolean PostQuestion(AlertType type,const StringPtr error,const StringPtr detail)
  93. {
  94.     AlertStdAlertParamRec        param;
  95.     short                        item;
  96.     
  97.     
  98.     // Ensure we are front process.
  99.     PreflightNotice(false);
  100.     
  101.     // Do it our way..call CompatibleStandardAlert and we'll be done.
  102.     param.movable = false;
  103.     param.helpButton = false;
  104.     param.filterProc = NULL;
  105.     param.defaultText = (StringPtr)-1L;                // default = "OK"
  106.     param.cancelText = (StringPtr)-1L;                // default = "Cancel'
  107.     param.otherText = NULL;                            // no other button
  108.     param.defaultButton = kAlertStdAlertOKButton;
  109.     param.cancelButton = kAlertStdAlertCancelButton;
  110.     param.position = 0;                                // Alert position on main screen
  111.     
  112.     CompatibleStandardAlert(type,error,detail,¶m,&item);
  113.     
  114.     return (item == 1);
  115. }
  116.  
  117.  
  118.  
  119.  
  120.  
  121. #define kCSATextBoxTop                9
  122. #define kCSATextBoxLeft                76
  123. #define kCSATextBoxWidth            (368 - kCSATextBoxLeft - 10)
  124. #define kCSATextBoxSeparator        5
  125. #define kCSATextBoxCompensation        10
  126.  
  127. typedef struct CSAInfo
  128. {
  129.     StringPtr    errorText;
  130.     StringPtr    detailText;
  131.     AlertType    alertType;
  132. } CSAInfo;
  133.  
  134. OSErr CompatibleStandardAlert(AlertType inAlertType,StringPtr inError,StringPtr inExplanation,
  135.                             AlertStdAlertParamPtr inAlertParam,SInt16 *outItemHit)
  136. {
  137.     DialogPtr    dialog;
  138.     
  139.     
  140.     if (gHasAppearance)
  141.         return StandardAlert(inAlertType,inError,inExplanation,inAlertParam,outItemHit);
  142.     
  143.     dialog = GetNewDialog(1000,NULL,(WindowPtr)(-1L));
  144.     if (dialog)
  145.     {
  146.         QDContext    context(dialog);
  147.         UserItemUPP    userItemUPP;
  148.         SInt16        iType,errHeight,detailHeight,height;
  149.         Point        loc;
  150.         Handle        iHandle;
  151.         Rect        iRect;
  152.         UInt32        size;
  153.         CSAInfo        info;
  154.         
  155.         
  156.         info.errorText = inError;
  157.         info.detailText = inExplanation;
  158.         info.alertType = inAlertType;
  159.         SetWRefCon(dialog,(long)&info);
  160.         
  161.         userItemUPP = NewUserItemProc(CompatibleStandardAlertUserItem);
  162.         errHeight = DrawAutoSizedText(inError,systemFont,12,0,0,kCSATextBoxWidth,false);
  163.         detailHeight = DrawAutoSizedText(inExplanation,applFont,10,0,0,kCSATextBoxWidth,false);
  164.         
  165.         height = errHeight + detailHeight + ((errHeight && detailHeight) ? (kCSATextBoxSeparator - kCSATextBoxCompensation) : 0);
  166.         SizeWindow(dialog,dialog->portRect.right,dialog->portRect.bottom + height,false);
  167.         
  168.         GetDialogItem(dialog,1,&iType,&iHandle,&iRect);
  169.         OffsetRect(&iRect,0,height);
  170.         SetDialogItem(dialog,1,iType,iHandle,&iRect);
  171.         MoveControl((ControlHandle)iHandle,iRect.left,iRect.top);
  172.         GetDialogItem(dialog,2,&iType,&iHandle,&iRect);
  173.         OffsetRect(&iRect,0,height);
  174.         SetDialogItem(dialog,2,iType,iHandle,&iRect);
  175.         MoveControl((ControlHandle)iHandle,iRect.left,iRect.top);
  176.         GetDialogItem(dialog,3,&iType,&iHandle,&iRect);
  177.         iRect.bottom += height + kCSATextBoxCompensation;
  178.         SetDialogItem(dialog,3,iType,(Handle)userItemUPP,&iRect);
  179.         
  180.         if (inAlertParam->defaultButton)
  181.             SetDialogDefaultItem(dialog,inAlertParam->defaultButton);
  182.         if (!inAlertParam->defaultText)
  183.         {
  184.             GetDialogItem(dialog,1,&iType,&iHandle,&iRect);
  185.             HideControl((ControlHandle)iHandle);
  186.         }
  187.         
  188.         if (inAlertParam->cancelButton)
  189.             SetDialogCancelItem(dialog,inAlertParam->cancelButton);
  190.         if (!inAlertParam->cancelText)
  191.         {
  192.             GetDialogItem(dialog,2,&iType,&iHandle,&iRect);
  193.             HideControl((ControlHandle)iHandle);
  194.         }
  195.         
  196.         ShowWindow(dialog);
  197.         ModalDialog(NULL,outItemHit);
  198.         
  199.         DisposeRoutineDescriptor(userItemUPP);
  200.         DisposeDialog(dialog);
  201.     }
  202.     
  203.     return 0;
  204. }
  205.  
  206.  
  207.  
  208.  
  209.  
  210. pascal void CompatibleStandardAlertUserItem(WindowPtr window,short item)
  211. {
  212.     QDContext    context(window);
  213.     CSAInfo        *info = (CSAInfo*)GetWRefCon(window);
  214.     short        offset,iconID;
  215.     
  216.     
  217.     switch(info->alertType)
  218.     {
  219.         case kAlertStopAlert:
  220.             iconID = 0;
  221.             break;
  222.         
  223.         case kAlertNoteAlert:
  224.             iconID = 1;
  225.             break;
  226.         
  227.         case kAlertCautionAlert:
  228.             iconID = 2;
  229.             break;
  230.             
  231.         default:
  232.             iconID = -1;
  233.             break;
  234.     }
  235.     
  236.     if (iconID != -1)
  237.     {
  238.         CIconHandle    cicon;
  239.         Rect        box;
  240.         
  241.         
  242.         box.left = 20;
  243.         box.top = 9;
  244.         box.right = box.left + 32;
  245.         box.bottom = box.top + 32;
  246.         
  247.         cicon = GetCIcon(iconID);
  248.         if (cicon)
  249.         {
  250.             PlotCIcon(&box,cicon);
  251.             DisposeCIcon(cicon);
  252.         }
  253.         else
  254.         {
  255.             Handle    icon;
  256.             
  257.             icon = GetIcon(iconID);
  258.             if (icon)
  259.             {
  260.                 PlotIcon(&box,icon);
  261.                 ReleaseResource(icon);
  262.             }
  263.         }
  264.     }
  265.     
  266.     offset = DrawAutoSizedText(info->errorText,systemFont,12,kCSATextBoxLeft,kCSATextBoxTop,kCSATextBoxWidth,true);
  267.     DrawAutoSizedText(info->detailText,applFont,10,kCSATextBoxLeft,offset + kCSATextBoxSeparator,kCSATextBoxWidth,true);
  268. }
  269.  
  270.  
  271.  
  272.  
  273.  
  274. short DrawAutoSizedText(StringPtr text,short font,short size,short left,short top,short width,Boolean draw)
  275. {
  276.     QDContext    context;
  277.     FontInfo    fInfo;
  278.     Str255        ctext;
  279.     UInt32        index,len,start,end;
  280.     short        cur;
  281.     
  282.     
  283.     if (!text || !(*text))
  284.         return top;
  285.     
  286.     TextFont(font);
  287.     TextSize(size);
  288.     GetFontInfo(&fInfo);
  289.     
  290.     pstrcpy(ctext,text);
  291.     len = 1 + ctext[0];
  292.     start = end = 1;
  293.     
  294.     for (index = 1;index < len;index++)
  295.     {
  296.         if (isspace(ctext[index]))
  297.         {
  298.             cur = TextWidth(ctext,start,index - start);
  299.             if (cur > width)
  300.             {
  301.                 if (draw)
  302.                 {
  303.                     MoveTo(left,top + fInfo.ascent);
  304.                     DrawText(ctext,start,end - start);
  305.                 }
  306.                 
  307.                 start = end + 1;
  308.                 top += fInfo.ascent + fInfo.descent + fInfo.leading;
  309.             }
  310.             
  311.             end = index;
  312.         }
  313.     }
  314.     
  315.     if (draw)
  316.     {
  317.         MoveTo(left,top + fInfo.ascent);
  318.         DrawText(ctext,start,index - start);
  319.     }
  320.     
  321.     top += fInfo.ascent + fInfo.descent;
  322.     return top;
  323. }
  324.  
  325.  
  326.  
  327.  
  328.  
  329. Boolean WeAreFrontProcess(void)
  330. {
  331.     ProcessSerialNumber        myPSN,frontPSN;
  332.     Boolean                    same;
  333.     
  334.     
  335.     GetCurrentProcess(&myPSN);
  336.     GetFrontProcess(&frontPSN);
  337.     SameProcess(&myPSN,&frontPSN,&same);
  338.     return same;
  339. }
  340.